package com.example.vaultmysql.controller;

import com.example.vaultmysql.entity.TestExecution;
import com.example.vaultmysql.service.ConcurrencyTestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * 测试控制器
 * 提供高并发测试相关的API接口
 * 
 * @author System
 * @version 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/api/test")
@CrossOrigin(origins = "*")
public class TestController {

    @Autowired
    private ConcurrencyTestService concurrencyTestService;

    /**
     * 启动高并发测试
     */
    @PostMapping("/start")
    public ResponseEntity<Map<String, Object>> startTest(@RequestBody TestRequest request) {
        try {
            // 验证请求参数
            if (request.getTestName() == null || request.getTestName().trim().isEmpty()) {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "message", "测试名称不能为空"
                ));
            }
            
            if (request.getDatabaseNames() == null || request.getDatabaseNames().isEmpty()) {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "message", "至少需要选择一个数据库"
                ));
            }
            
            if (request.getConcurrentUsers() <= 0 || request.getConcurrentUsers() > 1000) {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "message", "并发用户数必须在1-1000之间"
                ));
            }
            
            if (request.getDurationSeconds() <= 0 || request.getDurationSeconds() > 3600) {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "message", "测试持续时间必须在1-3600秒之间"
                ));
            }
            
            // 启动测试
            CompletableFuture<TestExecution> future = concurrencyTestService.startConcurrencyTest(
                request.getTestName(),
                request.getDatabaseNames(),
                request.getConcurrentUsers(),
                request.getDurationSeconds(),
                request.getQueryType() != null ? request.getQueryType() : TestExecution.QueryType.SELECT,
                request.getCreator() != null ? request.getCreator() : "anonymous"
            );
            
            TestExecution testExecution = future.get();
            
            return ResponseEntity.ok(Map.of(
                "success", true,
                "message", "测试启动成功",
                "testId", testExecution.getId(),
                "testName", testExecution.getTestName(),
                "status", testExecution.getStatus().toString()
            ));
            
        } catch (Exception e) {
            log.error("启动测试失败", e);
            return ResponseEntity.badRequest().body(Map.of(
                "success", false,
                "message", "启动测试失败: " + e.getMessage()
            ));
        }
    }

    /**
     * 停止测试
     */
    @PostMapping("/stop/{testId}")
    public ResponseEntity<Map<String, Object>> stopTest(@PathVariable Long testId) {
        try {
            boolean stopped = concurrencyTestService.stopTest(testId);
            
            if (stopped) {
                return ResponseEntity.ok(Map.of(
                    "success", true,
                    "message", "测试已停止",
                    "testId", testId
                ));
            } else {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "message", "无法停止测试，测试可能已经结束或不存在"
                ));
            }
            
        } catch (Exception e) {
            log.error("停止测试失败: testId={}", testId, e);
            return ResponseEntity.badRequest().body(Map.of(
                "success", false,
                "message", "停止测试失败: " + e.getMessage()
            ));
        }
    }

    /**
     * 获取测试状态
     */
    @GetMapping("/status/{testId}")
    public ResponseEntity<TestExecution> getTestStatus(@PathVariable Long testId) {
        try {
            TestExecution testExecution = concurrencyTestService.getTestStatus(testId);
            
            if (testExecution != null) {
                return ResponseEntity.ok(testExecution);
            } else {
                return ResponseEntity.notFound().build();
            }
            
        } catch (Exception e) {
            log.error("获取测试状态失败: testId={}", testId, e);
            return ResponseEntity.badRequest().build();
        }
    }

    /**
     * 获取正在运行的测试
     */
    @GetMapping("/running")
    public ResponseEntity<List<TestExecution>> getRunningTests() {
        try {
            List<TestExecution> runningTests = concurrencyTestService.getRunningTests();
            return ResponseEntity.ok(runningTests);
        } catch (Exception e) {
            log.error("获取正在运行的测试失败", e);
            return ResponseEntity.badRequest().build();
        }
    }

    /**
     * 获取测试历史
     */
    @GetMapping("/history")
    public ResponseEntity<List<TestExecution>> getTestHistory(
            @RequestParam(defaultValue = "10") int limit) {
        try {
            List<TestExecution> history = concurrencyTestService.getTestHistory(limit);
            return ResponseEntity.ok(history);
        } catch (Exception e) {
            log.error("获取测试历史失败", e);
            return ResponseEntity.badRequest().build();
        }
    }

    /**
     * 获取测试统计信息
     */
    @GetMapping("/statistics")
    public ResponseEntity<Map<String, Object>> getTestStatistics() {
        try {
            Map<String, Object> statistics = concurrencyTestService.getTestStatistics();
            return ResponseEntity.ok(statistics);
        } catch (Exception e) {
            log.error("获取测试统计信息失败", e);
            return ResponseEntity.badRequest().build();
        }
    }

    /**
     * 创建简单性能测试
     */
    @PostMapping("/simple")
    public ResponseEntity<Map<String, Object>> createSimpleTest(@RequestBody SimpleTestRequest request) {
        try {
            if (request.getDatabaseName() == null || request.getDatabaseName().trim().isEmpty()) {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "message", "数据库名称不能为空"
                ));
            }
            
            int concurrentUsers = request.getConcurrentUsers() > 0 ? request.getConcurrentUsers() : 10;
            int durationSeconds = request.getDurationSeconds() > 0 ? request.getDurationSeconds() : 60;
            
            // 限制参数范围
            concurrentUsers = Math.min(Math.max(concurrentUsers, 1), 100);
            durationSeconds = Math.min(Math.max(durationSeconds, 10), 300);
            
            CompletableFuture<TestExecution> future = concurrencyTestService.createSimplePerformanceTest(
                request.getDatabaseName(),
                concurrentUsers,
                durationSeconds
            );
            
            TestExecution testExecution = future.get();
            
            return ResponseEntity.ok(Map.of(
                "success", true,
                "message", "简单测试启动成功",
                "testId", testExecution.getId(),
                "testName", testExecution.getTestName(),
                "concurrentUsers", concurrentUsers,
                "durationSeconds", durationSeconds
            ));
            
        } catch (Exception e) {
            log.error("创建简单测试失败", e);
            return ResponseEntity.badRequest().body(Map.of(
                "success", false,
                "message", "创建简单测试失败: " + e.getMessage()
            ));
        }
    }

    /**
     * 清理旧测试记录
     */
    @PostMapping("/cleanup")
    public ResponseEntity<Map<String, Object>> cleanupOldTests(
            @RequestParam(defaultValue = "7") int daysOld) {
        try {
            concurrencyTestService.cleanupCompletedTests(daysOld);
            
            return ResponseEntity.ok(Map.of(
                "success", true,
                "message", "清理完成",
                "daysOld", daysOld
            ));
            
        } catch (Exception e) {
            log.error("清理旧测试记录失败", e);
            return ResponseEntity.badRequest().body(Map.of(
                "success", false,
                "message", "清理失败: " + e.getMessage()
            ));
        }
    }

    /**
     * 测试请求对象
     */
    public static class TestRequest {
        private String testName;
        private List<String> databaseNames;
        private int concurrentUsers;
        private int durationSeconds;
        private TestExecution.QueryType queryType;
        private String creator;
        
        // Getters and Setters
        public String getTestName() { return testName; }
        public void setTestName(String testName) { this.testName = testName; }
        
        public List<String> getDatabaseNames() { return databaseNames; }
        public void setDatabaseNames(List<String> databaseNames) { this.databaseNames = databaseNames; }
        
        public int getConcurrentUsers() { return concurrentUsers; }
        public void setConcurrentUsers(int concurrentUsers) { this.concurrentUsers = concurrentUsers; }
        
        public int getDurationSeconds() { return durationSeconds; }
        public void setDurationSeconds(int durationSeconds) { this.durationSeconds = durationSeconds; }
        
        public TestExecution.QueryType getQueryType() { return queryType; }
        public void setQueryType(TestExecution.QueryType queryType) { this.queryType = queryType; }
        
        public String getCreator() { return creator; }
        public void setCreator(String creator) { this.creator = creator; }
    }

    /**
     * 简单测试请求对象
     */
    public static class SimpleTestRequest {
        private String databaseName;
        private int concurrentUsers;
        private int durationSeconds;
        
        // Getters and Setters
        public String getDatabaseName() { return databaseName; }
        public void setDatabaseName(String databaseName) { this.databaseName = databaseName; }
        
        public int getConcurrentUsers() { return concurrentUsers; }
        public void setConcurrentUsers(int concurrentUsers) { this.concurrentUsers = concurrentUsers; }
        
        public int getDurationSeconds() { return durationSeconds; }
        public void setDurationSeconds(int durationSeconds) { this.durationSeconds = durationSeconds; }
    }
}